from PyQt4.QtGui  import QAction
from PyQt4.QtCore import SIGNAL

import gui
from cmdobjects import *
from cmdbase import *

# ---------------------------------------------------------------------------
#  Base action class
# ---------------------------------------------------------------------------

class _QActionWrapper(object):
   '''The base action class, which wraps a QAction. The QAction itself is
   stored in the action property. Subclasses should have the following
   properties:
   call              A lambda or function which is called when the action is
                     triggered.
   docstring         This is used as the context help.
   requires          The event that must be valid for the action to be enabled
   icon              The icon to display.
   text              The text to display.
   toggle            An event to which this action is linked. If this is specified, 
                     call need not be.
   suppress_command  If this is set (even to None), an undo command will not be generated.
   '''

   __instances = {}

   def __new__(cls, parent):
      if cls not in cls.__instances:
         self = cls.__instances[cls] = object.__new__(cls)
         self.action = QAction(self.text, parent)

         if hasattr(self, 'shortcut'): self.action.setShortcut  (self.shortcut)
         self.action.setStatusTip (self.__doc__)
         self.action.setToolTip   (self.__doc__)
         self.action.setText      (self.text)
         self.action.setWhatsThis (self.__doc__)

         # Events
         self.evt_calling = Event()

         # Refresh the gui whenever a change is made
         #(~self.evt_calling).bind(gui.Manager().refresh)

         self.action.connect(self.action, SIGNAL('triggered()'), self.__call)

         if hasattr(self, 'requires'):
            cls.requires.bind(lambda *args, **kwargs: self.action.setEnabled(True))
            (~cls.requires).bind(lambda *args, **kwargs: self.action.setEnabled(False))
            self.action.setEnabled(cls.requires.valid)
            
         if hasattr(self, 'toggle'):
            self.action.setCheckable(True)
            self.action.setChecked(self.checked)
            self.action.connect(self.action, SIGNAL('toggle(checked)'), self.__toggle)

      return cls.__instances[cls]

   def __toggle(self, checked):
      if checked:
         self.toggle()
      else:
         (~self.toggle)()

   def __call(self):
      self.evt_calling()
      if not hasattr(self, 'suppress_command'): beginMacro(self.text.replace('&', ''))
      self.call()
      if not hasattr(self, 'suppress_command'): endMacro()
      (~self.evt_calling)()

   def call(self):
      '''This function should be overloaded to provide the code for the action.'''
      pass


# Refer to QActionWrapper as Action to improve readability
Action = _QActionWrapper


